/**
 * WebDAV 客户端类，封装WebDAV协议API
 */

// 国际化支持函数
function getWebDAVMessage(key) {
  if (typeof chrome !== 'undefined' && chrome.i18n) {
    return chrome.i18n.getMessage(key) || key;
  }
  return key;
}
class WebDAVClient {
  /**
   * 构造函数
   * @param {string} serverUrl - WebDAV服务器地址
   * @param {string} username - 用户名
   * @param {string} password - 密码
   */
  constructor(serverUrl, username, password) {
    this.serverUrl = serverUrl.endsWith('/') ? serverUrl.slice(0, -1) : serverUrl;
    this.username = username;
    this.password = password;
    this.authHeader = 'Basic ' + btoa(username + ':' + password);
  }

  /**
   * 获取请求URL
   * @param {string} path - 资源路径
   * @returns {string} - 完整的请求URL
   */
  getRequestUrl(path) {
    // 规范化：确保path以/开头
    let normalized = typeof path === 'string' ? path : String(path || '/');
    if (!normalized.startsWith('/')) normalized = '/' + normalized;

    console.log(`[WebDAV] getRequestUrl 调试:`);
    console.log(`  - 输入路径: ${path}`);
    console.log(`  - 规范化后: ${normalized}`);
    console.log(`  - 服务器URL: ${this.serverUrl}`);

    // 坚果云特殊处理：确保路径格式正确
    if (this.serverUrl.includes('jianguoyun.com') || this.serverUrl.includes('nutstore.net')) {
      console.log(`  - 检测到坚果云服务`);
      
      // 坚果云需要确保路径格式为 /path 而不是 //path
      if (normalized === '/') {
        // 根路径直接返回服务器URL
        const result = this.serverUrl;
        console.log(`  - 根路径，返回: ${result}`);
        return result;
      }
      
      // 移除开头的斜杠，避免双斜杠
      const cleanPath = normalized.startsWith('/') ? normalized.slice(1) : normalized;
      console.log(`  - 清理后路径: ${cleanPath}`);
      
      // 将每个路径段进行编码，但保留斜杠
      const encoded = cleanPath
        .split('/')
        .map((seg, idx) => (idx === 0 ? seg : encodeURIComponent(seg)))
        .join('/');
      
      const result = this.serverUrl + '/' + encoded;
      console.log(`  - 坚果云最终URL: ${result}`);
      return result;
    }

    // 其他WebDAV服务器的标准处理
    const encoded = normalized
      .split('/')
      .map((seg, idx) => (idx === 0 ? '' : encodeURIComponent(seg)))
      .join('/');

    // 避免出现 serverUrl//path
    const result = this.serverUrl + (encoded === '' ? '/' : encoded);
    console.log(`  - 标准WebDAV最终URL: ${result}`);
    return result;
  }

  /**
   * 发送WebDAV请求
   * @param {string} method - HTTP方法
   * @param {string} path - 资源路径
   * @param {Object} options - 请求选项
   * @returns {Promise<Response>}
   */
  async request(method, path, options = {}) {
    const url = this.getRequestUrl(path);
    
    console.log(`[WebDAV] 开始 ${method} 请求`);
    console.log(`[WebDAV] 目标URL: ${url}`);
    console.log(`[WebDAV] 服务器地址: ${this.serverUrl}`);
    console.log(`[WebDAV] 用户名: ${this.username}`);
    console.log(`[WebDAV] 请求路径: ${path}`);
    console.log(`[WebDAV] 请求选项:`, options);
    
    const headers = {
      'Authorization': this.authHeader,
      ...options.headers
    };

    // 对PUT默认设置通用Content-Type，除非外部已指定
    if (method === 'PUT' && !headers['Content-Type']) {
      headers['Content-Type'] = 'application/octet-stream';
    }
    
    console.log(`[WebDAV] 完整请求头:`, headers);
    if (options.body) {
      console.log(`[WebDAV] 请求体类型:`, options.body.constructor?.name || typeof options.body);
    }
    
    try {
      console.log(`[WebDAV] 发送fetch请求...`);
      const startTime = Date.now();
      
      const response = await fetch(url, {
        method,
        headers,
        body: options.body
      });
      
      const endTime = Date.now();
      console.log(`[WebDAV] 请求耗时: ${endTime - startTime}ms`);
      console.log(`[WebDAV] 响应状态: ${response.status} ${response.statusText}`);
      console.log(`[WebDAV] 响应头:`, Object.fromEntries(response.headers.entries()));
      
      if (!response.ok) {
        const errorText = await response.text().catch(() => '无法读取错误信息');
        console.error(`[WebDAV] HTTP错误响应:`, errorText);
        
        // 坚果云特殊错误处理
        if (errorText.includes('AncestorsNotFound')) {
          throw new Error(getWebDAVMessage('errorPathNotFound'));
        } else if (errorText.includes('IllegalArgument')) {
          throw new Error(getWebDAVMessage('errorPathFormat'));
        } else if (errorText.includes('HTTP 409')) {
          throw new Error(getWebDAVMessage('errorResourceConflict'));
        } else if (errorText.includes('HTTP 403') && method === 'DELETE') {
          throw new Error(getWebDAVMessage('errorDeletePermission'));
        } else if (errorText.includes('HTTP 403')) {
          throw new Error(getWebDAVMessage('errorPermission'));
        } else if (errorText.includes('HTTP 401')) {
          throw new Error(getWebDAVMessage('errorAuth'));
        } else if (errorText.includes('HTTP 404')) {
          throw new Error(getWebDAVMessage('errorNotFound'));
        } else if (errorText.includes('HTTP 500')) {
          throw new Error(getWebDAVMessage('errorServerInternal'));
        }
        
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      console.log(`[WebDAV] 请求成功完成`);
      return response;
    } catch (error) {
      console.error(`[WebDAV] 请求失败:`, {
        错误类型: error.name,
        错误信息: error.message,
        错误堆栈: error.stack,
        请求URL: url,
        请求方法: method
      });
      
      // 提供更详细的错误分析
      if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
        console.error(`[WebDAV] 网络连接失败，可能原因:`);
        console.error(`  1. 服务器地址不正确: ${this.serverUrl}`);
        console.error(`  2. 网络连接问题`);
        console.error(`  3. CORS跨域限制`);
        console.error(`  4. 服务器未运行或不可访问`);
      } else if (error.message.includes('401')) {
        console.error(`[WebDAV] 认证失败，请检查用户名和密码`);
      } else if (error.message.includes('404')) {
        console.error(`[WebDAV] 路径不存在: ${path}`);
      }
      
      throw error;
    }
  }

  /**
   * 获取目录内容
   * @param {string} path - 目录路径
   * @returns {Promise<Array>} - 文件和文件夹列表
   */
  async listDirectory(path = '/') {
    console.log('=== WebDAV listDirectory 开始 ===');
    console.log('请求参数:');
    console.log('- 路径:', path);
    console.log('- 完整URL:', this.getRequestUrl(path));
    console.log('- 用户名:', this.username);
    
    const propfindBody = `<?xml version="1.0" encoding="utf-8" ?>
    <propfind xmlns="DAV:">
      <prop>
        <resourcetype/>
        <getcontentlength/>
        <getlastmodified/>
        <displayname/>
      </prop>
    </propfind>`;

    console.log('PROPFIND请求体:', propfindBody);
    
    const headers = {
        'Depth': '1',
        'Content-Type': 'text/xml'
    };
    
    console.log('请求头:', headers);
    console.log('发送PROPFIND请求...');

    try {
        const startTime = Date.now();
        const response = await this.request('PROPFIND', path, {
            headers: headers,
            body: propfindBody
        });
        const endTime = Date.now();

        console.log('=== HTTP响应信息 ===');
        console.log('响应时间:', (endTime - startTime) + 'ms');
        console.log('状态码:', response.status);
        console.log('状态文本:', response.statusText);

        const xmlText = await response.text();
        console.log('=== XML响应内容 ===');
        console.log('XML长度:', xmlText.length);
        console.log('XML内容:', xmlText);
        
        console.log('=== 开始解析XML ===');
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
        
        // 检查XML解析错误
        const parseError = xmlDoc.getElementsByTagName('parsererror')[0];
        if (parseError) {
            console.log('XML解析错误:', parseError.textContent);
            throw new Error('XML解析失败: ' + parseError.textContent);
        }

        // 命名空间无关的元素查询辅助
        const getElements = (node, localName) => {
          const set = new Set();
          const pushAll = (list) => Array.from(list || []).forEach(el => set.add(el));
          pushAll(node.getElementsByTagName(localName));
          try { pushAll(node.getElementsByTagNameNS('DAV:', localName)); } catch (e) {}
          try { pushAll(node.getElementsByTagNameNS('*', localName)); } catch (e) {}
          return Array.from(set);
        };
        const getFirst = (node, localName) => getElements(node, localName)[0] || null;
        
        // 使用命名空间无关的方式获取 response 列表
        let responses = getElements(xmlDoc, 'response');
        console.log('找到response元素数量:', responses.length);
        
        const items = [];

        // 计算服务端基路径（用于将 href 归一化为应用内路径）
        let serverBasePath = '/';
        try {
          const serverUrlObj = new URL(this.serverUrl);
          serverBasePath = serverUrlObj.pathname || '/';
        } catch (e) {
          console.warn('无法解析 serverUrl，使用默认基路径 /:', this.serverUrl);
        }
        // 规范化：确保基路径无尾部斜杠（根路径除外）
        if (serverBasePath !== '/' && serverBasePath.endsWith('/')) {
          serverBasePath = serverBasePath.slice(0, -1);
        }
        const normalizeHrefPath = (rawHref) => {
          try {
            let hrefPath = rawHref || '';
            // 提取路径部分
            if (/^https?:\/\//i.test(hrefPath)) {
              hrefPath = new URL(hrefPath).pathname;
            }
            hrefPath = decodeURIComponent(hrefPath);
            if (!hrefPath.startsWith('/')) hrefPath = '/' + hrefPath;
            // 将服务器基路径剥离成应用路径（例如 /dav/xxx -> /xxx）
            if (serverBasePath !== '/' && (hrefPath === serverBasePath || hrefPath === serverBasePath + '/')) {
              return '/';
            }
            if (serverBasePath !== '/' && hrefPath.startsWith(serverBasePath + '/')) {
              return hrefPath.slice(serverBasePath.length); // 保留前导 /
            }
            return hrefPath; // 已是根相对路径
          } catch (e) {
            console.warn('归一化 href 失败，返回原始值:', rawHref, e);
            return rawHref;
          }
        };
        
        for (let i = 0; i < responses.length; i++) {
            const response = responses[i];
            const hrefEl = getFirst(response, 'href');
            const href = hrefEl ? hrefEl.textContent : null;
            
            console.log(`处理第${i+1}个response:`);
            console.log('- href:', href);
            
            if (!href) {
                console.log('- 跳过: href为空');
                continue;
            }
            
            // 归一化 href -> 应用相对路径（与传入的 path 保持同一坐标系）
            const normalizedPath = normalizeHrefPath(href);
            console.log('- 归一化路径:', normalizedPath, '（基于 serverBasePath:', serverBasePath, '）');
            
            // 跳过当前目录 - 修复：使用更宽松的比较逻辑
            const requestedPath = path.endsWith('/') ? path.slice(0, -1) : path;
            const normalizedPathTrimmed = normalizedPath.endsWith('/') ? normalizedPath.slice(0, -1) : normalizedPath;
            
            // 只跳过完全匹配当前请求路径的项目
            if (normalizedPathTrimmed === requestedPath && normalizedPathTrimmed !== '') {
                console.log('- 跳过: 当前目录 (精确匹配)');
                continue;
            }
            
            // 额外检查：如果是根目录请求，跳过空路径或根路径本身
            if (path === '/' && (normalizedPath === '/' || normalizedPath === '')) {
                console.log('- 跳过: 根目录本身');
                continue;
            }
            
            const propstat = getFirst(response, 'propstat');
            if (!propstat) {
                console.log('- 跳过: propstat为空');
                continue;
            }
            
            const prop = getFirst(propstat, 'prop');
            if (!prop) {
                console.log('- 跳过: prop为空');
                continue;
            }
            
            const resourcetype = getFirst(prop, 'resourcetype');
            const isDirectory = !!resourcetype && getElements(resourcetype, 'collection').length > 0;
            
            const contentLength = getFirst(prop, 'getcontentlength')?.textContent || '0';
            const lastModified = getFirst(prop, 'getlastmodified')?.textContent || '';
            const displayName = getFirst(prop, 'displayname')?.textContent || '';
            
            console.log('- 属性解析:');
            console.log('  - resourcetype存在:', !!resourcetype);
            console.log('  - 是否为目录:', isDirectory);
            console.log('  - contentLength:', contentLength);
            console.log('  - lastModified:', lastModified);
            console.log('  - displayName:', displayName);
            
            // 从归一化路径中提取文件名
            let name = displayName || normalizedPath.split('/').filter(Boolean).pop() || '';
            console.log('  - 最终名称:', name);
            
            const item = {
                name: name,
                path: normalizedPath,
                type: isDirectory ? 'directory' : 'file',
                isDirectory: isDirectory,
                size: parseInt(contentLength) || 0,
                lastModified: lastModified ? new Date(lastModified) : null
            };
            
            items.push(item);
            console.log('- 项目已添加:', `${item.name} (${item.isDirectory ? '目录' : '文件'})`);
        }
        
        console.log('=== XML解析完成 ===');
        console.log('解析结果:');
        console.log('- 总项目数:', items.length);
        console.log('- 目录数:', items.filter(item => item.isDirectory).length);
        console.log('- 文件数:', items.filter(item => !item.isDirectory).length);
        
        return items;
        
    } catch (error) {
        console.error('ERROR: 获取目录内容失败:', error);
        throw error;
    }
  }

  /**
   * 创建目录
   * @param {string} path - 目录路径
   * @returns {Promise<Response>}
   */
  async createDirectory(path) {
    console.log(`[WebDAV] 开始创建目录: ${path}`);
    
    try {
      // 检查父目录是否存在
      const parentPath = this.getParentPath(path);
      if (parentPath && parentPath !== '/') {
        try {
          console.log(`[WebDAV] 检查父目录是否存在: ${parentPath}`);
          await this.request('PROPFIND', parentPath, { headers: { 'Depth': '0' } });
          console.log(`[WebDAV] 父目录存在，可以创建子目录`);
        } catch (parentError) {
          console.error(`[WebDAV] 父目录不存在: ${parentPath}`, parentError);
          throw new Error(`无法创建目录：父目录 "${parentPath}" 不存在，请先创建父目录`);
        }
      }
      
      const response = await this.request('MKCOL', path);
      console.log(`[WebDAV] 目录创建成功: ${path}`);
      return response;
    } catch (error) {
      console.error(`[WebDAV] 创建目录失败: ${path}`, error);
      throw error;
    }
  }

  /**
   * 获取父目录路径
   * @param {string} path - 当前路径
   * @returns {string} - 父目录路径
   */
  getParentPath(path) {
    if (!path || path === '/') return null;
    
    const normalized = path.endsWith('/') ? path.slice(0, -1) : path;
    const parts = normalized.split('/').filter(Boolean);
    
    if (parts.length <= 1) return '/';
    
    parts.pop(); // 移除最后一部分
    return '/' + parts.join('/');
  }

  /**
   * 上传文件
   * @param {string} path - 文件路径
   * @param {Blob|File} fileData - 文件数据
   * @returns {Promise<Response>}
   */
  async uploadFile(path, file) {
    return await this.request('PUT', path, {
        body: file
    });
  }

  /**
   * 下载文件
   * @param {string} path - 文件路径
   * @returns {Promise<Blob>}
   */
  async downloadFile(path) {
    console.log(`[WebDAV] 开始下载文件: ${path}`);
    
    try {
      const response = await this.request('GET', path);
      
      // 检查响应状态
      if (!response.ok) {
        throw new Error(`下载失败: HTTP ${response.status} ${response.statusText}`);
      }
      
      // 获取文件内容为Blob
      const blob = await response.blob();
      
      console.log(`[WebDAV] 文件下载成功: ${path}`, {
        size: blob.size,
        type: blob.type
      });
      
      return blob;
    } catch (error) {
      console.error(`[WebDAV] 下载文件失败: ${path}`, error);
      throw error;
    }
  }

  /**
   * 删除文件或目录
   * @param {string} path - 资源路径
   * @returns {Promise<Response>}
   */
  async delete(path) {
    return await this.request('DELETE', path);
  }

  /**
   * 移动或重命名资源
   * @param {string} sourcePath - 源路径
   * @param {string} destinationPath - 目标路径
   * @returns {Promise<Response>}
   */
  async move(fromPath, toPath) {
    return await this.request('MOVE', fromPath, {
        headers: {
            'Destination': this.getRequestUrl(toPath)
        }
    });
  }
}

// 导出WebDAV客户端类
if (typeof module !== 'undefined') {
  module.exports = { WebDAVClient };
} else {
  window.WebDAVClient = WebDAVClient;
}